package com.magold.physics;

import java.util.LinkedList;
import java.util.List;

import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.entity.shape.IAreaShape;

import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.magold.logic.ISpriteLogic;

/**
 * Body -> IAreaShape -> Customize(such as: ISpriteLogic, Region);
 * And we can get PhysicsConnector of IAreaShape through Customize.
 * 
 * @author Eternity
 *
 */
public class MagoldContactListener implements ContactListener, IUpdateHandler {
	private final List<Contact> mBeginContacts;
	private final List<Contact> mEndContacts;

	public MagoldContactListener() {
		mBeginContacts = new LinkedList<Contact>();
		mEndContacts = new LinkedList<Contact>();
	}

	/**
	 * Called when two fixtures begin to touch.
	 * 
	 */
	@Override
	public void beginContact(Contact contact) {
		mBeginContacts.add(contact);
	}

	/**
	 * Called when two fixtures cease to touch.
	 */
	@Override
	public void endContact(Contact contact) {
		mEndContacts.add(contact);
	}

	@Override
	public void preSolve(Contact contact, Manifold oldManifold) {
	}

	@Override
	public void postSolve(Contact contact, ContactImpulse impulse) {
	}

	@Override
	public void onUpdate(float pSecondsElapsed) {
		for (Contact contact : mBeginContacts) {
			process(contact, true);
		}
		mBeginContacts.clear();

		for (Contact contact : mEndContacts) {
			process(contact, false);
		}
		mEndContacts.clear();
	}

	private void process(Contact pContact, boolean pBegin) {
		if (!valid(pContact)) return;

		Fixture fa = pContact.getFixtureA();
		Fixture fb = pContact.getFixtureB();
		Body bodyA = fa.getBody();
		Body bodyB = fb.getBody();
		
		IAreaShape o1 = (IAreaShape) bodyA.getUserData();
		IAreaShape o2 = (IAreaShape) bodyB.getUserData();

		Object d1 = o1.getUserData();
		Object d2 = o2.getUserData();
		
		ISpriteLogic l2 = (ISpriteLogic) d2;
		ISpriteLogic l1 = (ISpriteLogic) d1;
		
//		Log.d("MagoldContactListener", l1.getClass().getSimpleName() + (pBegin ? " start " : " cease ") + " to collide with " + l2.getClass().getSimpleName());
		
		if (pBegin) {
			l2.startCollide(l1, pContact);
			if (!valid(pContact)) return;
			l1.startCollide(l2, pContact);
		} else {
			l2.endCollide(l1, pContact);
			if (!valid(pContact)) return;
			l1.endCollide(l2, pContact);
		}
	}
	
	private boolean valid(Contact pContact) {
		Fixture fa = pContact.getFixtureA();
		Fixture fb = pContact.getFixtureB();
		return fa!=null && fb!=null;
	}

	@Override
	public void reset() {

	}

}
